var componentText = (function () {
    Array.prototype.remove = function (val) {
        var index = this.indexOf(val);
        if (index > -1) {
            this.splice(index, 1);
        }
    };
    Array.prototype.unique = function () {
        this.sort();
        var temp = [this[0]];
        this.forEach(function (item) {
            if (item !== temp[temp.length - 1]) {
                temp.push(item);
            }
        })
        return temp;
    };
    var Component = function () {
        this.selectNodeId = 1;
        this.historyData = [];
        this.maxLevel = 999;
        this._initEvent();
    };
    Component.prototype = {
        construcor: Component,
        constant: {
            DEFAULT_DATA: [
                {
                    id: 1,
                    pId: null,
                    title: '',
                    hasTitle: true,
                    name: '',
                    children: [],
                    type: {level: 0, accept: [1]},
                    row: 12
                },
            ],
            MENU_LAST_STAT: '<div data-role="_level_" class="heatMap-section heatMap-layout" id="_id_" data-id="_id_">' +
            '<div class="heatMap-item-inner" data-role="name" data-id="_id_" title="_name_">_name_',
            MENU_OTHER_STAT: '<div data-role="_level_" class="heatMap-section heatMap-layout _rowClass_" id="_id_" data-id="_id_">' +
            '<div class="heatMap-layout-head _isNone_" data-role="title" title="_title_">_title_</div>' +
            '<div data-role="_level_-droppable" class="heatMap-layout-ctt" data-id="_id_">',
            DIV_END: '</div></div>',
            MAXLEVEL: 4,
            TYPES: [
                {
                    num: 0,
                    level: 0,
                    droppableStr: ".heatMap-content [data-role='level-0-droppable']",
                    acceptStr: "[data-role='level-1']"
                },
                {
                    num: 0,
                    level: 1,
                    droppableStr: ".heatMap-content [data-role='level-1-droppable']",
                    acceptStr: "[data-role='level-2']"
                },
                {
                    num: 0,
                    level: 2,
                    droppableStr: ".heatMap-content [data-role='level-2-droppable']",
                    acceptStr: "[data-role='level-3']"
                },
                {
                    num: 0,
                    level: 3,
                    droppableStr: ".heatMap-content [data-role='level-3-droppable']",
                    acceptStr: "[data-role='level-4']"
                },
                {num: 0, level: 4, droppableStr: ".heatMap-content [data-role='level-4']", acceptStr: null}
            ]

        },
        init: function (options) {
            var that = this;
            //是否data不为空，为空则使用默认TYPS，并设置maxLevel=3，
            // 主要是为了后续_createMenu和_createContent调用不同模板做准备
            if (data && data.length) {
                that._getTypes(data);
            } else {
                that.maxLevel = that.constant.MAXLEVEL;
            }
            //生成视图框架
            that._createLayout(options.id);
            //生成视图
            that._createMenu();
            that._createContent(data);
            //事件调用
            that._myDroppable();
            that._myDraggable();
            that._mySortable();
            layui.use('form');
        },
        _initEvent: function () {
            var oldRow,
                that = this;
            document.addEventListener('click', function (event) {
                var target,
                    $updata,
                    formData;
                target = event.target;
                $updata = $('[data-role="heatMap-item-updata"]');
                for (var key in target.attributes) {
                    switch (target.attributes[key].value) {
                        case 'heatMap-title-save':
                            layer.msg('save' + that.getData());
                            break;
                        case 'updata-save':
                            formData=that._getFormData();
                            that._upData($("#" + that.selectNodeId), 'updata', formData);
                            that._upView(formData,oldRow);
                            $updata.slideUp("slow");
                            break;
                        case 'updata-cancel':
                            $updata.slideUp("slow");
                            break;
                    }
                }
                if (target.closest('.heatMap-section') && $(target.closest('.heatMap-section')).data('id').length > 10) {
                    that.selectNodeId = $(target.closest('.heatMap-section')).data('id');
                    that.historyData.forEach(function (item) {
                        if (item['id'] === that.selectNodeId) {
                            that.selectNode = item;
                        }
                        ;
                    })
                    $('[data-role="heatMap-item-updata"]').slideDown("slow");
                    oldRow=that._echoForm($(target.closest('.heatMap-section')).data('id'));
                }
            });
            $(document).delegate('[lay-skin="_switch"]', 'click', function () {
                var $checkBox = $('#checkboxShowTitle'),
                    $thisItem = $checkBox.closest('.layui-form-item'),
                    $nextItem = $thisItem.next();
                if ($checkBox.attr("checked") && $thisItem.find('em').text()==='OFF') {
                    $checkBox.attr("checked", false);
                    $nextItem.slideUp();
                    $nextItem.find(':text').val("");
                } else {
                    $checkBox.attr("checked", true);
                    $nextItem.slideDown();
                }
            })

        },
        _createLayout: function (id) {
            var $template,
                template = '<div data-role="layout" class="layout">' +
                    '<div data-role="heatMap-title" class="row-12" style="width: 1107px">' +
                    '<div data-role="heatMap-title-title" class="heatMap-group-btn-title">服务热点地图</div>' +
                    '<div data-role="heatMap-title-save" class="heatMap-group-btn">保存</div>' +
                    '</div>' +
                    '<div data-role="heatMap-menu" class="heatMap-menu" ></div>' +
                    '<div data-role="heatMap-right" class="heatMap-right layui-form layui-form-pane" style="width:1067px;height: 600px">' +
                    '<div data-role="heatMap-item-updata" class="heatMap-item-updata">' +
                    '<div class="layui-form-item">' +
                    '<label class="layui-form-label">ID</label>' +
                    '<div class="layui-input-block">' +
                    '<input data-id="item-id" type="text" name="title" required disabled autocomplete="off" class="layui-input">' +
                    '</div>' +
                    '</div>' +
                    '<div class="layui-form-item" pane>' +
                    '<label class="layui-form-label">PID</label>' +
                    '<div class="layui-input-block">' +
                    '<input  data-id="item-pId" type="text" name="title" required disabled lay-verify="required" autocomplete="off" class="layui-input">' +
                    '</div>' +
                    '</div>' +

                    '<div class="layui-form-item" pane>' +
                    '<label class="layui-form-label">节点名称</label>' +
                    '<div class="layui-input-block">' +
                    '<input data-id="item-name" type="text" name="title" required  lay-verify="required" placeholder="请输入节点名称" autocomplete="off" class="layui-input">' +
                    '</div>' +
                    '</div>' +
                    '<div class="layui-form-item">' +
                    '<label class="layui-form-label">层级</label>' +
                    '<div class="layui-input-block">' +
                    '<input data-id="item-type-level" type="text" name="title" required  lay-verify="required" placeholder="请输入类型" autocomplete="off" class="layui-input">' +
                    '</div>' +
                    '</div>' +
                    '<div class="layui-form-item">' +
                    '<label class="layui-form-label">可放置区域</label>' +
                    '<div class="layui-input-block">' +
                    '<input data-id="item-type-accept" type="text" name="title" required  lay-verify="required" placeholder="请输入类型" autocomplete="off" class="layui-input">' +
                    '</div>' +
                    '</div>' +
                    '<div class="layui-form-item">' +
                    '<label class="layui-form-label">跨度</label>' +
                    '<div class="layui-input-block">' +
                    '<select data-id="item-row" name="city" lay-verify="required">' +
                    '<option value=""></option>' +
                    '<option value=1>1</option>' +
                    '<option value=2>2</option>' +
                    '<option value=3>3</option>' +
                    '<option value=4>4</option>' +
                    '<option value=5>5</option>' +
                    '<option value=6>6</option>' +
                    '<option value=7>7</option>' +
                    '<option value=8>8</option>' +
                    '<option value=9>9</option>' +
                    '<option value=10>10</option>' +
                    '<option value=11>11</option>' +
                    '<option value=12>12</option>' +
                    '</select>' +
                    '<div id="item-row-shade-ctn"></div>' +
                    '</div>' +
                    '</div>' +
                    '<div class="layui-form-item">' +
                    '<label class="layui-form-label">显示标题</label>' +
                    '<div class="layui-input-block" style="position:relative;">' +
                    '<input data-id="item-hasTitle" id="checkboxShowTitle" value=true type="checkbox" name="yyy" lay-skin="switch" lay-text="ON|OFF" checked>' +
                    '<div id="item-hasTitle-shade-ctn"></div>' +
                    '</div>' +
                    '</div>' +
                    '<div data-role="item-canTrigger-title" class="layui-form-item">' +
                    '<label class="layui-form-label">标题</label>' +
                    '<div class="layui-input-block">' +
                    '<input  data-id="item-title" type="text" name="title" required  lay-verify="required" placeholder="请输入标题" autocomplete="off" class="layui-input">' +
                    '</div>' +
                    '</div>' +
                    '<div class="layui-form-item"><div class="layui-input-block">' +
                    '<button data-role="updata-save" class="layui-btn" >暂存</button>' +
                    '<button data-role="updata-cancel" class="layui-btn layui-btn-primary">取消</button></div></div>' +
                    '</div>' +
                    '<div data-role="heatMap-content" class="heatMap-content"></div>' +
                    '</div>' +
                    '</div>';
            $template = $(template);
            $template.find('[data-role="heatMap-item-updata"]').slideUp("slow");
            $("#" + id).append($template);
        },
        _getLevels: function (data) {
            var that = this,
                arr = [];
            data.forEach(function (item) {
                arr.push(item.type.level)
            });
            //对数组排序并去重，以便生成TYPES和maxLevel
            arr = arr.unique();
            that.maxLevel = arr[arr.length - 1];
            return arr;
        },
        _getTypes: function (data) {
            var tempTYPES = [],
                that = this,
                levels = that._getLevels(data);
            levels.forEach(function (oneLevel) {
                var flag = true;
                data.forEach(function (item) {
                    if (flag && oneLevel === item.type.level) {
                        var obj = {};
                        obj.num = 0;
                        obj.level = item.type.level;
                        obj.level === that.maxLevel ? obj.droppableStr = ".heatMap-content [data-role='level-" + item.type.level + "']" : obj.droppableStr = ".heatMap-content [data-role='level-" + item.type.level + "-droppable']";
                        obj.acceptStr = item.type.accept ? item.type.accept.map(function (one) {
                            return "[data-role='level-" + one + "']"
                        }).join(",") : null;
                        tempTYPES.push(obj);
                        flag = false;
                    }
                });
            });
            that.constant.TYPES = tempTYPES;
        },
        _createMenu: function () {
            var that = this,
                html = [],
                CONST = that.constant,
                template = '', $template;
            that.constant.TYPES.forEach(function (item) {
                //是否为最后一层如果是则使用专有的html模板
                if (item.level === that.maxLevel) {
                    html.push(CONST.MENU_LAST_STAT
                        .replace(/_name_/g, item.level)
                        .replace(/_level_/g, "level-" + item.level));
                    html.push(CONST.DIV_END);
                } else {
                    html.push(CONST.MENU_OTHER_STAT
                        .replace(/_title_/g, item.level)
                        .replace(/_rowClass_/g, "row-6")
                        .replace(/_level_/g, "level-" + item.level));
                    html.push(CONST.DIV_END);
                }
            });
            template = html.join('');
            $template = $(template);
            $template.addClass('heatMap-menu-item');
            $("[data-role='heatMap-menu']").append($template);
        },
        _createContent: function (param) {
            this.constant.DEFAULT_DATA.id = this._getUUID();
            var cursor,
                CONST = this.constant,
                template = '',
                html = [],
                seek = [],
                map = {},
                that = this,
                i = -1,
                //获得data，如果data为空则使用默认的数据（仅有最底层level）
                tempData = param && param.length ? param : that.constant.DEFAULT_DATA,
                data = JSON.parse(JSON.stringify(tempData));
            that.historyData = data;
            //对data进行初步处理
            while (item = data[++i]) {
                if (!item.pId) {
                    //获取初始化遍历数组seek
                    seek.push(item)
                }
                //生成哈希值
                map[item.id] = item;
            }
            i = -1;
            while (item = seek[++i]) {
                cursor = i;
                if (item.type === 'html') {
                    html.push(item.content);
                } else {
                    //如果子元素为字符串则通过map获取该子元素
                    if (typeof item === 'string') {
                        item = map[item];
                    }
                    if (item.type.level === that.maxLevel) {
                        html.push(CONST.MENU_LAST_STAT
                            .replace(/_name_/g, item.name)
                            .replace(/_id_/g, item.id)
                            .replace(/_level_/g, "level-" + item.type.level));
                        html.push(CONST.DIV_END);
                    } else {
                        html.push(CONST.MENU_OTHER_STAT
                            .replace(/_title_/g, item.title)
                            .replace(/_id_/g, item.id)
                            .replace(/_rowClass_/g, "row-" + item.row)
                            .replace(/_level_/g, "level-" + item.type.level)
                            .replace(/_isNone_/g, item.hasTitle ? '' : "is-none")
                        );
                        //利用数组的splice的插入功能将子元素插入父元素之后
                        if (item.children && item.children.length) {
                            seek.splice.apply(seek, [cursor + 1, 0]
                                //concat进行拼接数组
                                    .concat(item.children)
                                    .concat([{
                                        type: 'html',
                                        content: CONST.DIV_END
                                    }])
                            );
                        } else {
                            html.push(CONST.DIV_END);
                        }
                    }
                }

            }
            template = html.join('');
            $("[data-role='heatMap-content']").append($(template));

        },
        _upView: function (formData, oldRow) {
            debugger;
            var that = this,
                $select=$("#"+that.selectNodeId),
                $selectHead=$select.children().filter('.heatMap-layout-head'),
                $selectInner=$select.children().find('.heatMap-item-inner'),
                oldRowClass = "row-" + oldRow,
                newRowClass = "row-" + formData.row;
            for(key in formData){
                switch (key){
                    case "hasTitle":
                        if(formData[key]){
                            if($selectHead.hasClass('is-none')){
                                $selectHead.removeClass('is-none');
                            }
                        }else{
                            $selectHead.addClass('is-none');
                        }
                        break;
                    case "title":
                        if(formData.hasTitle && formData[key].length){
                            $selectHead.text(formData[key]);
                        }
                        break;
                    case "row":
                        $select.removeClass(oldRowClass).addClass(newRowClass);
                        break;
                    case "name":
                        $selectInner.text(formData[key]);
                        break;
                }

            }
        },
        //放置
        _myDroppable: function () {
            var that = this;
            that.constant.TYPES.forEach(function (item) {
                $(item.droppableStr).droppable({
                    accept: item.acceptStr,
                    activeClass: 'ui-state-highlight',
                    drop: function (event, ui) {
                        //如果是从左侧菜单中拖入的对象则执行
                        if (ui.draggable.closest("[data-role='heatMap-menu']").length) {
                            //克隆脱出的对象并清除style(清除位置以及定位)
                            var uuId = that._getUUID(),
                                $template = ui.helper.clone().removeAttr('style').attr('id', uuId).data('id', uuId).removeClass('heatMap-menu-item'),
                                num = 0,
                                level = Number(
                                    $template.data('role') && $template.data('role').split('-').length ?
                                        $template.data('role').split('-')[1] : '-1'
                                );
                            //根据层级不同对当前层级编号进行叠加
                            that.constant.TYPES.forEach(function (item) {
                                if (level === item.level) {
                                    num = item.num++;
                                }
                            });
                            level !== -1 && level === that.maxLevel ? $template.find(':last-child').html("待定义节点" + num) : $template.find(':first-child').html("待定义层级" + level + "-" + num);
                            $template.find(':last-child').data('id', uuId);
                            $(this).append($template);
                            that._myDroppable();
                            that._mySortable();
                            that._addData($template);
                        }
                    }
                });
            });
        },
        //排序
        _mySortable: function () {
            var that = this;
            //排序一定要使用需要排序的父级作为容器
            $(that.constant.TYPES[that.constant.TYPES.length - 2].droppableStr).sortable({
                appendTo: document.body,
                cursor: 'pointer',
                tolerance: "pointer",
                opacity: 0.5,
                zIndex: 99999,
                //关联其他同级容器
                connectWith: that.constant.TYPES[that.constant.TYPES.length - 2].droppableStr,
                update: function (event, ui) {
                    that._upData(ui.item, 'sortable');
                }
            })
        },
        //拖动
        _myDraggable: function () {
            var that = this;
            $("[data-role='heatMap-menu'] .heatMap-layout").draggable({
                zIndex: 100,
                helper: 'clone'
            });
        },
        _getUUID: function () {
            var s = [];
            var hexDigits = "0123456789abcdef";
            for (var i = 0; i < 36; i++) {
                s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
            }
            s[14] = "4";
            s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
            s[8] = s[13] = s[18] = s[23] = "-";

            var uuid = s.join("");
            return uuid;

        },
        _addData: function ($element) {
            var defaultNode = {
                    id: '',
                    pId: '',
                    children: [],
                    row: 6,
                    hasTitle: true,
                    title: '',
                    name: '',
                    type: {level: 0, accept: []}
                },
                id = $element.data('id'),
                pId = $element.parent().data('id'),
                type = $element.data('role').split('-'),
                name = $element.find("[data-role='name']"),
                title = $element.find("[data-role='title']"),
                that = this,
                nowNode = defaultNode;
            nowNode.pId = pId;
            nowNode.id = id;
            nowNode.type.level = type.length === 2 ? Number(type[1]) : 0;
            type.length === 2 ? nowNode.type.accept.push(type[1] - 0 + 1) : nowNode.type.accept.push(1);
            nowNode.name = name[0] ? name[0].innerText : '';
            nowNode.title = title[0] ? title[0].innerText : '';
            if (nowNode.type.level === '0') {
                nowNode.row = 12;
            } else if (nowNode.type.level === that.constant.MAXLEVEL) {
                nowNode.row = 12;
                nowNode.hasTitle = false;
            }
            that.historyData.forEach(function (item) {
                if (item.id === pId) {
                    item.children.push(id);
                }
            });
            that.historyData.push(nowNode);
            console.log(JSON.stringify(that.historyData));
        },
        _delData: function () {

        },
        _upData: function ($element, flag, formData) {
            var that = this,
                id = $element.data('id');
            if (flag === 'sortable') {
                var nowNode,
                    prevParentNode,
                    nowParentId = $element.parent().data('id'),
                    nowParentNode;
                that.historyData.forEach(function (item) {
                    if (item['id'] === id) {
                        nowNode = item;
                    } else if (item['id'] === nowParentId) {
                        nowParentNode = item;
                    }
                })
                that.historyData.forEach(function (item) {
                    if (item['id'] === nowNode.pId) {
                        prevParentNode = item;
                    }
                });
                if (prevParentNode.id === nowParentNode.id) {
                    //循环并将数据位置更换
                    var index1, index2;
                    nowParentNode.children.forEach(function (item, index) {
                        //判断是否拖动的位置是最顶层
                        if ($element.prev().length) {
                            if (item === $element.prev().data('id')) {
                                index2 = index;
                            }
                        } else {
                            index2 = 0;
                        }
                        if (item === $element.data('id')) {
                            index1 = index;
                        }
                    });
                    nowParentNode.children = that._swapItem(nowParentNode.children, index1, index2);
                } else {
                    //判断是否拖动的位置是最顶层
                    if ($element.prev().length) {
                        //循环并将数据插入
                        nowParentNode.children.forEach(function (item, index) {
                            if (item === $element.prev().data('id')) {
                                nowParentNode.children.splice(index + 1, 0, id)
                            }
                        })
                    } else {
                        //如果是最顶层的直接在最前面添加即可
                        nowParentNode.children.unshift(id);
                    }
                    prevParentNode.children.remove(id);
                }
                nowNode.pId = nowParentId;
            } else if (flag === 'updata') {
                that.historyData.forEach(function (item) {
                    if (item['id'] === id) {
                        for (var key in item) {
                            if (key==='hasTitle' || formData[key]) {
                                item[key] = formData[key];
                            }
                        }
                    }
                });
            }
        },
        _getFormData: function () {
            var that = this,
                flag = false,
                result = {},
                arrOther = [
                    $('[data-id="item-hasTitle"]'),
                    $('[data-id="item-title"]'),
                    $('[data-id="item-row"]')
                ],
                arrMax = [
                    $('[data-id="item-name"]')
                ]
            if (that.selectNode.type.level === that.constant.MAXLEVEL) {
                if (arrMax[0] && arrMax[0].val() && arrMax[0].val().length) {
                    result.name = arrMax[0].val();
                }
            } else {
                arrOther.forEach(function (item) {
                    key = item.data('id').split('-')[1];
                    switch (key) {
                        case "title":
                            if(result['hasTitle']){
                                result[key] = item.val();
                            }
                            break;
                        case "hasTitle":
                            result[key] =item.attr("checked") ? true : false;
                            break;
                        case "row":
                            result[key] = Number(item.val());
                            break;
                    }
                })
            }
            return result;
        },
        _swapItem: function (arr, index1, index2) {
            arr[index1] = arr.splice(index2, 1, arr[index1])[0];
            return arr;
        },
        _echoForm: function (id) {
            var that = this,
                nowNode,
                selected,
                oldRow,
                $input = $(":text,:checkbox", '[data-role="heatMap-item-updata"]'),
                $select = $("select", '[data-role="heatMap-item-updata"]'),
                $options = $select.children(),
                $switch = $('[lay-skin="_switch"]');
            that.historyData.forEach(function (item) {
                if (item['id'] === id) {
                    nowNode = item;
                }
            });
            selected = nowNode['row'];
            if (nowNode['hasTitle']) {
                if (!($switch.hasClass('layui-form-onswitch'))) {
                    $switch.click();
                }
            } else {
                if ($switch.hasClass('layui-form-onswitch')) {
                    $switch.click();
                }
            }
            Array.prototype.slice.call($options).forEach(function (item) {
                var $item = $(item), dd;
                if (Number($item.val()) === selected) {
                    dd = 'dd[lay-value=' + Number($item.val()) + ']';
                    $('[data-role="heatMap-item-updata"]').find("div.layui-form-select").find('dl').find(dd).click();
                    oldRow = $item.val();
                }
            });
            Array.prototype.slice.call($input).forEach(function (item) {
                var oneEle = $(item),
                    key = oneEle.data('id') ? oneEle.data('id').split('-')[1] : '';
                if (key && key !== '') {
                    if (typeof nowNode[key] === 'object') {
                        one = oneEle.data('id').split('-').length === 3 ? oneEle.data('id').split('-')[2] : '';
                        oneEle.val(nowNode[key][one]);
                    } else {
                        oneEle.val(nowNode[key]);
                    }
                }
                oneEle.attr('disabled', false);
                $("#item-hasTitle-shade-ctn").removeClass('item-shade');
                $('#item-row-shade-ctn').removeClass('item-shade');
                $('.layui-form-item:eq(2)').removeClass('is-none');
            })
            Array.prototype.slice.call($input).forEach(function (item) {
                var $item = $(item);
                if (($item.data('id') && $item.data('id').split('-') && $item.data('id').split('-').length > 1) && (!$item.val() || $item.data('id').split('-')[1] === 'id' || $item.data('id').split('-')[1] === 'type' || $item.data('id').split('-')[1] === 'pId')) {
                    $item.attr("disabled", true);
                }
            });
            if (!(nowNode.hasTitle) && nowNode.type.level === that.constant.MAXLEVEL) {
                $("#item-hasTitle-shade-ctn").addClass('item-shade');
            }
            nowNode.type.level === that.constant.MAXLEVEL ? $('#item-row-shade-ctn').addClass('item-shade') : $('.layui-form-item:eq(2)').addClass('is-none');
            return oldRow;
        },
        getData: function () {
            return this.historyData;
        }
    };
    return Component;
})
();
$(function () {
    new componentText().init({id: 'app'});
});